package com.hcy.driverapi.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hcy.driver.DriverBaseInfoClient;
import com.hcy.driver.dto.request.*;
import com.hcy.driver.dto.response.DriverCarInfoResponseDTO;
import com.hcy.driverapi.dto.CompetitionOrderRequestDTO;
import com.hcy.mqclient.message.MessageServiceClient;
import com.hcy.ordermodel.dto.request.*;
import com.hcy.ordermodel.dto.response.SimpleOrderResponseDTO;
import com.hcy.rabbitbasicmodel.common.MyWebSocketMessage;
import com.hcy.rabbitbasicmodel.enums.Clients;
import com.hcy.rabbitbasicmodel.enums.M_Code;
import com.hcy.rabbitbasicutils.utils.RedisUtils;
import com.hcy.schedulingclient.client.SchedulingLocationClient;
import com.hcy.orderclient.OrderForDriverClient;
import com.hcy.rabbitbasicmodel.enums.Code;
import com.hcy.rabbitbasicmodel.enums.OrderStatus;
import com.hcy.rabbitbasicmodel.model.ResponseData;
import com.hcy.rabbitbasicmodel.model.ReturnResult;
import com.hcy.rabbitbasicutils.utils.MyHttpUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Author huchenying
 * @Description 司机端公共信息 TODO 司机做出操作后应该同步乘客端 websocket
 * @Date 2021/12/20 12:04
 */
@RestController
@RequestMapping("/api/location")
public class DriverRuntimeController {

    @Autowired
    MyHttpUtils myHttpUtils;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    SchedulingLocationClient schedulingLocationClient;

    @Resource
    OrderForDriverClient orderForDriverClient;

    @Autowired
    MessageServiceClient messageServiceClient;

    @Autowired
    DriverBaseInfoClient driverBaseInfoClient;


    private static final String GD_ADD_STRACK_URL = "https://tsapi.amap.com/v1/track/trace/add";

    private static final Logger logger = LoggerFactory.getLogger(DriverRuntimeController.class);

    /**
     * @Author huchenying
     * @Description 获取轨迹，绑定信息，然后返回
     * @Date 2021/12/20 12:05
     **/
    @PostMapping("/startBusiness")
    public ReturnResult getTrack(@RequestBody AddTrackRequestDTO requestDTO) {
        logger.info("getTrack start param -> {}", ToStringBuilder.reflectionToString(requestDTO));
        //TODO 校验司机发过来的验证码
        if (!requestDTO.getVcode().equals(1234)) {
            return ReturnResult.fail("验证码错误，请重新输入！");
        }
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("key", "5c940527e7a1a30ebf63600e3645adfc");
        params.add("sid", requestDTO.getSid());
        params.add("tid", requestDTO.getTid());
        MultiValueMap<String, String> header = new LinkedMultiValueMap<>();
        //创建轨迹
        Long trid = null;
        try {
            ReturnResult result = myHttpUtils.sendPostRequest(GD_ADD_STRACK_URL, params, header);
            logger.info("轨迹创建结果 -> {}", result);
            Object data = result.getData();
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(data));
            trid = jsonObject.getJSONObject("data").getLong("trid");
            logger.info("trid = [{}]", trid);
        } catch (Exception e) {
            logger.error("创建轨迹异常", e);
            // 容错处理
//            return ReturnResult.exception("系统异常！");
            trid = 0L;
        }
        //绑定订单轨迹 更新订单,给订单估价表创建数据
        BindTrackRequestDTO bindTrackRequestDTO = new BindTrackRequestDTO();
        BeanUtils.copyProperties(requestDTO, bindTrackRequestDTO);
        bindTrackRequestDTO.setTrid(trid);
        ResponseData<SimpleOrderResponseDTO> responseData = orderForDriverClient.bindTrack(bindTrackRequestDTO);
        if (responseData.getCode() == Code.Success) {
            Message message = new Message();
            MyWebSocketMessage myWebSocketMessage = new MyWebSocketMessage();
            myWebSocketMessage.setCode(M_Code.CustomerUpCarSuccess.getCode());
            myWebSocketMessage.setDesc(M_Code.CustomerUpCarSuccess.getDesc());
            myWebSocketMessage.setUsername(responseData.getData().getPassengerPhone());
            myWebSocketMessage.setClientId(Clients.CUSTOMER.getName());
            message.setTopic("WEBSOCKET");
            message.setBody(JSON.toJSONString(myWebSocketMessage).getBytes(StandardCharsets.UTF_8));
            messageServiceClient.pushAsyncMessage(message);
            return ReturnResult.success().setData(trid);
        }
        return ReturnResult.fail("请求错误！");
    }

    /**
     * @Author huchenying
     * @Description 去接乘客
     * @Date 2021/12/23 15:26
     * TODO 更新额外信息
     **/
    @PostMapping("/driverGoDo")
    public ReturnResult goDo(@Validated @RequestBody DriverGoDoRequestDTO requestDTO) {
        logger.info("goDo start param -> {}", ToStringBuilder.reflectionToString(requestDTO));
        UpdateOrderRequestDTO orderRequestDTO = new UpdateOrderRequestDTO();
        BeanUtils.copyProperties(requestDTO, orderRequestDTO);
        orderRequestDTO.setStatus(OrderStatus.DO.getCode());
        orderRequestDTO.setDriverStartTime(new Date());
        ResponseData<SimpleOrderResponseDTO> responseData = orderForDriverClient.updateOrder(orderRequestDTO);
        if (responseData.getCode() == Code.Success) {
            Message message = new Message();
            MyWebSocketMessage myWebSocketMessage = new MyWebSocketMessage();
            myWebSocketMessage.setCode(M_Code.DriverReadySuccess.getCode());
            myWebSocketMessage.setDesc(M_Code.DriverReadySuccess.getDesc());
            myWebSocketMessage.setUsername(responseData.getData().getPassengerPhone());
            myWebSocketMessage.setClientId(Clients.CUSTOMER.getName());
            message.setTopic("WEBSOCKET");
            message.setBody(JSON.toJSONString(myWebSocketMessage).getBytes(StandardCharsets.UTF_8));
            messageServiceClient.pushAsyncMessage(message);
            return ReturnResult.success();
        } else {
            return ReturnResult.fail("更新订单信息失败！");
        }
    }

    /**
     * @Author huchenying
     * @Description 到达乘客起点
     * @Date 2021/12/23 15:26
     *
     **/
    @PostMapping("/driverAtOrigin")
    public ReturnResult atOrigin(@Validated @RequestBody DriverAtOriginRequestDTO requestDTO) {
        logger.info("atOrigin start param -> {}", ToStringBuilder.reflectionToString(requestDTO));
        UpdateOrderRequestDTO orderRequestDTO = new UpdateOrderRequestDTO();
        BeanUtils.copyProperties(requestDTO, orderRequestDTO);
        orderRequestDTO.setStatus(OrderStatus.ORIGIN.getCode());
        orderRequestDTO.setDriverArrivedTime(new Date());
        ResponseData<SimpleOrderResponseDTO> responseData = orderForDriverClient.updateOrder(orderRequestDTO);
        if (responseData.getCode() == Code.Success) {
            Message message = new Message();
            MyWebSocketMessage myWebSocketMessage = new MyWebSocketMessage();
            myWebSocketMessage.setCode(M_Code.DriverArriveOrigin.getCode());
            myWebSocketMessage.setDesc(M_Code.DriverArriveOrigin.getDesc());
            myWebSocketMessage.setUsername(responseData.getData().getPassengerPhone());
            myWebSocketMessage.setClientId(Clients.CUSTOMER.getName());
            myWebSocketMessage.setData(M_Code.DriverArriveOrigin.getDesc());
            message.setTopic("WEBSOCKET");
            message.setBody(JSON.toJSONString(myWebSocketMessage).getBytes(StandardCharsets.UTF_8));
            messageServiceClient.pushAsyncMessage(message);
            return ReturnResult.success();
        } else {
            return ReturnResult.fail("更新订单信息失败！");
        }
    }

    /**
     * @Author huchenying
     * @Description 到达目的地, 完成订单
     * @Date 2021/12/23 16:16
     **/
    @PostMapping("/arrive")
    public ReturnResult arrive(@Validated @RequestBody DriverArriveRequestDTO requestDTO) {
        logger.info("arrive start param -> {}", ToStringBuilder.reflectionToString(requestDTO));
        //调用订单系统
        try {
            UpdateOrderRequestDTO orderRequestDTO = new UpdateOrderRequestDTO();
            BeanUtils.copyProperties(requestDTO, orderRequestDTO);
            ResponseData<SimpleOrderResponseDTO> responseData = orderForDriverClient.finishOrder(orderRequestDTO);
            if (responseData.getCode() == Code.Success) {
                //释放运力
                redisUtils.removeDriverRev(responseData.getData().getDriverId().toString());
                //发送消息
                Message message = new Message();
                MyWebSocketMessage myWebSocketMessage = new MyWebSocketMessage();
                myWebSocketMessage.setCode(M_Code.CustomerArriveTarget.getCode());
                myWebSocketMessage.setDesc(M_Code.CustomerArriveTarget.getDesc());
                myWebSocketMessage.setUsername(responseData.getData().getPassengerPhone());
                myWebSocketMessage.setClientId(Clients.CUSTOMER.getName());
                message.setTopic("WEBSOCKET");
                message.setBody(JSON.toJSONString(myWebSocketMessage).getBytes(StandardCharsets.UTF_8));
                messageServiceClient.pushAsyncMessage(message);
                return ReturnResult.success();
            } else {
                logger.error("完成订单失败！ error -> {}",ToStringBuilder.reflectionToString(responseData.getMsg()));
                return ReturnResult.fail("请求失败！");
            }
        } catch (BeansException e) {
            logger.error("e -> {}",ToStringBuilder.reflectionToString(e));
           return ReturnResult.fail("系统异常");
        }
    }

    /**
     * @Author huchenying
     * @Description 抢单 CAR_RUNTIME_STATUS 叫到车了车辆运行状态要改
     * @Date
     **/
    @PostMapping("/competitionOrder")
    public ReturnResult competitionOrder(@Validated @RequestBody CompetitionOrderRequestDTO requestDTO) {
        logger.info("competitionOrder start param -> {}", ToStringBuilder.reflectionToString(requestDTO));
        SimpleOrderResponseDTO resSimpleOrder = null;
        try {
            //验证一下，当前司机是否有单
//            String rev = redisUtils.getDriverRev(requestDTO.getDriverId().toString());
//            logger.info("rev -> {}",rev);
//            if (StringUtils.isNotEmpty(rev)) { //发现司机已经接了一单了，验证这一单的状态，如果是已取消或不是当前司机接的单就清除司机运力
//                //判断
//                DriverOrderRequestDTO requestDTO1 = new DriverOrderRequestDTO();
//                requestDTO1.setOrderNumber(rev);
//                ResponseData<SimpleOrderResponseDTO> simpleOrder = orderForDriverClient.getSimpleOrder(requestDTO1);
//                if (simpleOrder.getCode() != Code.Success
//                        || simpleOrder.getData().getStatus() != OrderStatus.CANCEL.getCode()) {
//                    //返回
//                    return ReturnResult.fail("当前状态异常，不能接单，确认是否已经接过实时单，请联系客服！");
//                }
//            }
            //判断订单状态
            //首先判断订单是否已经取消
            if (redisUtils.isOrderNotKeepAlive(requestDTO.getOrderNumber())) {
                logger.info("订单[{}]已经消费或取消，跳过消费", requestDTO.getOrderNumber());
                return ReturnResult.fail("手慢了，订单已经被抢走了！");
            }
            //获取分布式锁,锁20s
            boolean b = redisUtils.setIfAbsent("lock:" + requestDTO.getOrderNumber(), "1", 60, TimeUnit.SECONDS);
            if (!b) {
                //没获取锁，返回手慢了
                return ReturnResult.fail("手慢了，订单已经被抢走了！");
            }
            // 抢到锁了开始派单 status，driver_grab_time，driver_id，driver_phone，car_id
            AddDriverForOrderRequestDTO addDriverForOrderRequestDTO = new AddDriverForOrderRequestDTO();
            addDriverForOrderRequestDTO.setStatus(OrderStatus.RECV.getCode());
            addDriverForOrderRequestDTO.setOrderNumber(requestDTO.getOrderNumber());
            addDriverForOrderRequestDTO.setDriverId(requestDTO.getDriverId());
            // 查询其他信息
            DriverCarInfoRequestDTO driverCarInfoRequestDTO = new DriverCarInfoRequestDTO();
            driverCarInfoRequestDTO.setDriverId(requestDTO.getDriverId());
            ResponseData<DriverCarInfoResponseDTO> driverCarInfoResponseDTOResponseData = driverBaseInfoClient.driverCarInfo(driverCarInfoRequestDTO);
            if (driverCarInfoResponseDTOResponseData.getCode() != Code.Success) {
                //这块做处理，失败以后订单的逻辑
                return ReturnResult.fail("手慢了，订单已经被抢走了！");
            }
            logger.info("driverCarInfoResponseDTOResponseData -> {}", ToStringBuilder.reflectionToString(driverCarInfoResponseDTOResponseData));
            DriverCarInfoResponseDTO driverCarInfoResponseDTO = driverCarInfoResponseDTOResponseData.getData();
            //填充参数
            BeanUtils.copyProperties(driverCarInfoResponseDTO, addDriverForOrderRequestDTO);
            addDriverForOrderRequestDTO.setDriverGrabTime(new Date());
            addDriverForOrderRequestDTO.setDriverId(requestDTO.getDriverId());
            addDriverForOrderRequestDTO.setOrderNumber(requestDTO.getOrderNumber());
            ResponseData<SimpleOrderResponseDTO> responseData = orderForDriverClient.addDriverForOrder(addDriverForOrderRequestDTO);
            if (responseData.getCode() != Code.Success) {
                return ReturnResult.fail("手慢了，订单已经被抢走了！");
            }
            logger.info("responseData -> {}", ToStringBuilder.reflectionToString(responseData));
            resSimpleOrder = responseData.getData();
            //判断订单状态
            //首先判断订单是否已经取消
            if (redisUtils.isOrderNotKeepAlive(requestDTO.getOrderNumber())) {
                logger.info("订单[{}]已经消费或取消，跳过消费", requestDTO.getOrderNumber());
                return ReturnResult.fail("手慢了，订单已经被抢走了！");
            }
            // 派单完成更新redis记录，防止一辆车接多个单,订单完成时需要释放运力,key为司机ID，value为订单号
            redisUtils.setDriverRev(requestDTO.getDriverId().toString(), requestDTO.getOrderNumber());
            // 通知用户结果,用MQ向websoket服务发送消息
            Message message = new Message();
            message.setTopic("WEBSOCKET");
            MyWebSocketMessage webSocketMessage = new MyWebSocketMessage();
            webSocketMessage.setCode(M_Code.CallCarSuccess.getCode());
            webSocketMessage.setDesc(M_Code.CallCarSuccess.getDesc());
            webSocketMessage.setClientId(Clients.CUSTOMER.getName());
            webSocketMessage.setUsername(requestDTO.getCustomerId());
            driverCarInfoResponseDTO.setOrderNumber(resSimpleOrder.getOrderNumber());
            webSocketMessage.setData(JSON.toJSONString(driverCarInfoResponseDTO));
            message.setBody(JSON.toJSONString(webSocketMessage).getBytes(StandardCharsets.UTF_8));
            messageServiceClient.pushAsyncMessage(message);
            resSimpleOrder.setDriverId(requestDTO.getDriverId());
            resSimpleOrder.setCarId(requestDTO.getCarId());
        } catch (BeansException e) {
            logger.error("e-> {}",ToStringBuilder.reflectionToString(e));
            return ReturnResult.fail("系统异常");
        }
        return ReturnResult.success().setData(resSimpleOrder);
    }

    /**
     * @Author huchenying
     * @Description 司机取消订单
     * @Date 2022/3/19 21:15
     **/
    @PostMapping("/cancelOrder")
    public ReturnResult driverCancelOrder(@Validated @RequestBody CancelOrderRequestDTO requestDTO) {
        logger.info("driverCancelOrder start param -> {} ", ToStringBuilder.reflectionToString(requestDTO));
        try {
            //更新订单信息
            ResponseData<SimpleOrderResponseDTO> responseData = orderForDriverClient.driverCancelOrder(requestDTO);
            if(responseData.getCode() != Code.Success){
                logger.error("订单取消失败！");
                return ReturnResult.fail("取消失败！");
            }
            //清除rev
            redisUtils.removeDriverRev(responseData.getData().getDriverId().toString());
            SimpleOrderResponseDTO data = responseData.getData();
            //给乘客发信息
            Message message = new Message();
            message.setTopic("WEBSOCKET");
            MyWebSocketMessage webSocketMessage = new MyWebSocketMessage();
            webSocketMessage.setCode(M_Code.DriverCancelOrder.getCode());
            webSocketMessage.setDesc(M_Code.DriverCancelOrder.getDesc());
            webSocketMessage.setClientId(Clients.CUSTOMER.getName());
            webSocketMessage.setUsername(data.getPassengerPhone());
            webSocketMessage.setData(JSON.toJSONString(data));
            message.setBody(JSON.toJSONString(webSocketMessage).getBytes(StandardCharsets.UTF_8));
            messageServiceClient.pushAsyncMessage(message);
        } catch (Exception e) {
            logger.error("e -> {}",ToStringBuilder.reflectionToString(e));
            return ReturnResult.fail("系统异常");
        }
        return ReturnResult.success();
    }

}
